<?php
/**
 * Framework_Table_Common
 *
 * @author      Ian Szewczyk <roamzero@gmail.com>
 * @copyright   (c) 2007 Ian Szewczyk. All rights reserved.
 * @license     http://www.opensource.org/licenses/bsd-license.php
 * @package Framework
 * @subpackage Table
 * @filesource
 */

require_once 'DB/Table.php';

/**
 * Framework_Table_Common
 *
 * A common base class for our Tables, which basically
 * are DB_Table classes from the PEAR library
 *
 * @author Ian Szewczyk <roamzero@gmail.com>
 * @package Framework
 * @subpackage Table
 * @link http://pear.php.net/package/DB_Table
 */
abstract class Framework_DB_Table_Common extends DB_Table {

	/**
     * $create
     *
     * @access      public
     * @var         string		$create      How to handle table creation
     */
	public $create = 'safe';

	/**
     * $tableName
     *
     * @access      public
     * @var         string		$tableName      Name of table
     */
	public $tableName = null;

	/**
     * $record
     *
     * @access      public
     * @var         array		$record      Active record
     */
	public $record = array();

	/**
     * $isLoaded
     *
     * @access      public
     * @var         boolean		$isLoaded      Whether active record is loaded
     */
	public $isLoaded = false;

	/**
     * $fetchmode
     *
     * @access      public
     * @var         boolean		$fetchmode     Default Fetch Mode
     */
	public $fetchmode = MDB2_FETCHMODE_ASSOC;

	/**
     * $columns
     *
     * @access      public
     * @var         array		$columns      Array of column names
     */
	public $columns;

	/**
     * $filter
     *
     * @access      private
     * @var         string		$filter     A copy of filter for active record use
     */
	private $filter; // for updating purposes

	/**
	 * __construct
	 *
	 * @access 		public
	 * @param 		object 			$db 			Valid DB connection
	 * @return 		void
	 */
	public function __construct($db) {

		if(!$this->tableName) {
			throw new Framework_Exception('No Table name defined');
		}

		parent::DB_Table($db, $this->tableName, $this->create);

		if($this->error) {
			throw new Framework_Exception($this->error);
		}

		$this->columns = array_keys($this->col);
	}


	/**
     * select
     *
     * Data to select from database
     *
     * @access      public
     * @param       array       $args		Query array
     * @param       mixed     	$cacheHandler		Cache Handler object for loggin table dependencies
     * @return      mixed
     * @see         DB_Table::select
     */
	public function select($args, $cacheHandler = null)
	{

		if ($cacheHandler && $cacheHandler instanceof Framework_Cache_Handler_Common) {

			Framework_DB::logDependency($cacheHandler,$this->tableName);

		}

		if (is_array($args) && array_key_exists('sqlKey',$args)) {
			if(is_array($args['sqlKey'])) {
				$this->sql['sqlKey'] = $args['sqlKey'];
				$args['sqlKey'] = 'sqlKey';
			}
			return parent::select($args['sqlKey'], $args['filter'], $args['order'], $args['start'], $args['count'], $args['params']);
		} else {
			$internalArgs = func_get_args();
			return call_user_func_array(array('parent','select'),$internalArgs);
		}
	}

	/**
     * selectCount
     *
     * Get the number of rows a query would return
     *
     * @access      public
     * @param       array       $args		Query array
     * @param       mixed     	$cacheHandler		Cache Handler object for loggin table dependencies
     * @return      mixed
     * @see         DB_Table::selectCount
     */
	public function selectCount($args, $cacheHandler = null)
	{
		if ($cacheHandler && $cacheHandler instanceof Framework_Cache_Handler_Common) {

			Framework_DB::logDependency($cacheHandler,$this->tableName);

		}
		if (is_array($args) && array_key_exists('sqlKey',$args)) {
			if(is_array($args['sqlKey'])) {
				$this->sql['sqlKey'] = $args['sqlKey'];
				$args['sqlKey'] = 'sqlKey';
			}
			return parent::selectCount($args['sqlKey'], $args['filter'], $args['order'], $args['start'], $args['count'], $args['params']);
		} else {
			$internalArgs = func_get_args();
			return call_user_func_array(array('parent','selectCount'),$internalArgs);
		}
	}


	
	/**
     * selectResult
     *
     * Returns a result object to manualy get rows from the result set
     *
     * @access      public
     * @param       array       $args		Query array
     * @param       mixed     	$cacheHandler		Cache Handler object for loggin table dependencies
     * @return      mixed
     * @see         DB_Table::selectResult
     */
	public function selectResult($args, $cacheHandler = null)
	{

		if ($cacheHandler && $cacheHandler instanceof Framework_Cache_Handler_Common) {

			Framework_DB::logDependency($cacheHandler,$this->tableName);

		}

		if (is_array($args) &&  array_key_exists('sqlKey',$args)) {
			if(is_array($args['sqlKey'])) {
				$this->sql['sqlKey'] = $args['sqlKey'];
				$args['sqlKey'] = 'sqlKey';
			}
			return parent::selectResult($args['sqlKey'], $args['filter'], $args['order'], $args['start'], $args['count'], $args['params']);
		} else {
			$internalArgs = func_get_args();
			return call_user_func_array(array('parent','selectResult'),$internalArgs);
		}
	}

	/**
     * Insert
     *
     * Insert a row in teh table
     *
     * @access      public
     * @param       array     	$data		Data for the update
     * @param       string     	$group		What cache group is being affected
     * @return      mixed
     * @see         DB_Table::insert
     */
	public function insert($data, $group = null)
	{

		Framework_DB::clearCache($this->tableName, $group);
		return  parent::insert($data);
	}

	/**
     * update
     *
     * Update data in the database
     *
     * @access      public
     * @param       array     	$data		Data for the update
     * @param       mixed     	$where		Where clause
     * @param       string     	$group		What cache group is being affected
     * @return      mixed
     * @see         DB_Table::update
     */
	public function update($data, $where, $group = null)
	{
		Framework_DB::clearCache($this->tableName,$group);
		
		if (is_array($where)) {
			require_once 'DB/Table/Database.php';

			$where = DB_Table_Database::buildFilter($where);
		}
		
		return  parent::update($data, $where);
	}

	/**
     * getCol
     *
     * Returns column information for specific or all columns in table
     *
     * @access      public
	 * @param       mixed     	$col		Column to look up
     * @return      mixed
     * @see         DB_Table::getColumns
     */
	public function getCol($col = null)
	{
		return $this->getColumns($col);
	}

	/**
     * delete
     *
     * Delete data in the database
     *
     * @access      public
	 * @param       mixed     	$where		Where clause
     * @param       string     	$group		What cache group is being affected
     * @return      mixed
     * @see         DB_Table::delete
     */
	public function delete($where, $group = null)
	{
		Framework_DB::clearCache($this->tableName,$group);
		if (is_array($where)) {
			require_once 'DB/Table/Database.php';

			$where = DB_Table_Database::buildFilter($where);
		}

		return  parent::delete($where);
	}

	/**
     * load
     *
     * loads an active record
     *
     * @access      public
	 * @param       mixed     	$where		Where clause
     * @param       mixed     	$cacheHandler		Cache Handler object for use with query
     * @return      mixed
     */
	public function load($where, $cacheHandler = null)
	{
		$this->record = null;

		require_once 'DB/Table/Database.php';

		if (is_array($where)) {
			$filter = DB_Table_Database::buildFilter($where);
		} else {
			$filter = $where;
		}

		$this->filter = $filter;

		$sql = array(
			'select' => '*',
			'get'    => 'row'
		);
			
		$options = array();
		$options['sqlKey'] = $sql;
		$options['filter'] = $filter;

		$this->record = $this->select($options, $cacheHandler);
		

		if (count($this->record)) {
			$this->isLoaded = true;
			return true;
		} elseif(PEAR::isError($this->record)) {
			return $this->record;
		}

	}

	/**
     * save
     *
     * saves an active record
     *
     * @access      public
	 * @param       mixed     	$group		Cache group affected
     * @return      mixed
     */
	public function save($group = null)
	{

		if ($this->isLoaded) {
			// Need to update
			$result = $this->update($this->record, $this->filter, $group);
			if (PEAR::isError($result)) {
				return $result;
			}
		} else {
			// Need to Insert
			if(!PEAR::isError($this->record)) {
				if (count($this->record)) {
					$result = $this->insert($this->record, $group);
					if (PEAR::isError($result)) {
						return $result;
					}
				}
			} else {
				return PEAR::raiseError('Invalid Record:'.$this->record->getMessage());
			}
		}

		if (!PEAR::isError($result)) {
			return true;
		}  else {
			return $result;
		}

	}

	/**
     * resetRecord
     *
     * resets the current record
     *
     * @access      public
     * @return      void
     */
	public function resetRecord()
	{
		// Start clean
		$this->isLoaded = false;

		$this->record = null;
	}


	/**
     * resetRecord
     *
     * resets the current record
     *
     * @access      private
     * @param 		string		$var		Column name to validate
     * @return      boolean
     */
	private function checkVar($var){

		if (in_array($var, $this->columns)) {
			return true;
		} else {
			return false;
		}

	}

	/**
	 * __set
	 *
	 * @access public
	 * @return void
	 * @see Framework_Module::setData()
	 */
	public function __set($var,$val)
	{

		// need to make sure the var is a valid
		if ($this->checkVar($var)) {
			$this->record[$var] = $val;
		}
	}

	/**
	 * __get
	 *
	 * @access public
	 * @return mixed
	 * @see Framework_Module::$data
	 */
	public function __get($var)
	{
		 
		if (!$this->checkVar($var)) {
			return false;
		}
		 
		if (!isset($this->record[$var])) {
			$this->record[$var] = null;
		}

		return $this->record[$var];
	}

	/**
     * __sleep
     *
     * invoked upon serialization
     *
     * @access      public
	 * @return      array
     */
	public function __sleep()
	{

		$this->filter = null;
		$this->isLoaded = false;
		$this->record = null;
		$this->db = null;
		$this->_database = null;
		return array_keys( get_object_vars( $this ) );

	}

	/**
     * __wakeup
     *
     * invoked upon unserialization
     *
     * @access      public
	 * @return      void
     */
	public function __wakeup()
	{
		
		$this->db = Framework_DB::getDBConnection();
	}






} 

?>
